package com.jxmcloud.business.cut.service.impl.user;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.jxmcloud.business.cut.constants.CutSaveKey;
import com.jxmcloud.business.cut.dtoCommon.TurnItemDto;
import com.jxmcloud.business.cut.dtoCommon.TurntableInfo;
import com.jxmcloud.business.cut.enums.TurnDisplayRulesType;
import com.jxmcloud.business.cut.enums.TurnGetConditionType;
import com.jxmcloud.business.cut.json.DataConfigService;
import com.jxmcloud.business.cut.model.database.DBUserTurntable;
import com.jxmcloud.business.cut.service.database.IUserTurntableDBService;
import com.jxmcloud.business.cut.service.logic.IConfigActionUtil;
import com.jxmcloud.business.cut.service.user.IUserBagService;
import com.jxmcloud.business.cut.service.user.IUserDrawTurnService;
import com.jxmcloud.business.cut.service.user.IUserFlowService;
import com.jxmcloud.business.cut.vo.json.ConfigAwardVo;
import com.jxmcloud.business.cut.vo.json.ConfigGlobalGlobalVo;
import com.jxmcloud.business.cut.vo.json.ConfigWheelInfoVo;
import com.jxmcloud.business.cut.vo.user.PlayerInfoVo;
import com.jxmcloud.business.cut.vo.user.UserTurnItem;
import com.jxmcloud.business.cut.vo.user.UserTurnTableVo;
import org.assertj.core.util.Sets;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

@Service
public class UserDrawTurnServiceImpl implements IUserDrawTurnService {
    @Resource
    private DataConfigService dataConfigService;
    @Resource
    private IConfigActionUtil configActionUtil;
    @Resource
    private IUserBagService userBagService;
    @Resource
    private IUserTurntableDBService userTurntableDBService;
    @Resource
    private IUserFlowService userFlowService;

    @Override
    public UserTurnItem startTurnTable(PlayerInfoVo player) {
        // 获取转盘所有数据
        UserTurnTableVo turnTable = player.getTurnTable();
        List<UserTurnItem> turnItemList = turnTable.getTurnData();
        int turnMax = turnTable.getAwardList().size();
        for (UserTurnItem userTurnItem : turnItemList) {
            //
            Integer awardId = userTurnItem.getAwardId();
            ConfigAwardVo awardConfig = dataConfigService.getConfigAwardConfig(awardId);
            if (ObjectUtil.isNull(awardConfig)) {
                continue;
            }
            // 是否所有条件都满足
            boolean isAllFit = false;
            Integer[][] conditionList = awardConfig.getGetCondition();
            for (int i = 0; i < conditionList.length; ++i) {
                isAllFit = false;
                Integer[] condition = conditionList[i];
                if (ObjectUtil.isNull(condition) || condition.length < 2) {
                    continue;
                }
                Integer type = condition[0]; // 条件类型
                Integer value = condition[1];// 条件值
                // 抽奖次数
                if (type.equals(TurnGetConditionType.SUCCEED.getValue())) {
                    if (!value.equals(turnMax + 1)) { // 不满足
                        break;
                    }
                } else if (type.equals(TurnGetConditionType.HIDE_POOL.getValue())) {
                    // 隐藏池子分
                    ConfigGlobalGlobalVo globalConfig = dataConfigService.getConfigGlobalGlobalConfig();
                    if (ObjectUtil.isNull(globalConfig)) {
                        continue;
                    }
                    Integer itemCount = userBagService.getItemCount(player, globalConfig.getItemIdPool());
                    if (itemCount < value) { // 不满足
                        break;
                    }
                } else {
                    continue;
                }
                //
                isAllFit = true;
            }
            if (isAllFit) {
                return userTurnItem;
            }
        }
        player.getMaster().getSaveList().add(CutSaveKey.USER_TURNTABLE);
        return null;
    }

    @Override
    public UserTurnItem startSpecialTurnTable(PlayerInfoVo player) {
        // 获取转盘所有数据
        UserTurnTableVo turnTable = player.getTurnTable();
        //获取转盘
        List<ConfigAwardVo> turnList = configActionUtil.getAwardPoolById(turnTable.getPoolId());
        if (ObjectUtil.isNull(turnList)) {
            return null;
        }
        int turnMax = turnTable.getAwardList().size();
        for (ConfigAwardVo configAwardVo : turnList) {
            // 是否所有条件都满足
            boolean isAllFit = false;
            Integer[][] conditionList = configAwardVo.getGetCondition();
            for (int i = 0; i < conditionList.length; ++i) {
                Integer[] condition = conditionList[i];
                if (ObjectUtil.isNull(condition) || condition.length < 2) {
                    continue;
                }
                Integer type = condition[0]; // 条件类型
                Integer value = condition[1];// 条件值
                // 抽奖次数
                if (type.equals(TurnGetConditionType.SUCCEED.getValue())) {
                    if (!value.equals(turnMax + 1)) { // 不满足
                        break;
                    }
                } else if (type.equals(TurnGetConditionType.HIDE_POOL.getValue())) {
                    // 隐藏池子分
                    ConfigGlobalGlobalVo globalConfig = dataConfigService.getConfigGlobalGlobalConfig();
                    if (ObjectUtil.isNull(globalConfig)) {
                        continue;
                    }
                    Integer itemCount = userBagService.getItemCount(player, globalConfig.getItemIdPool());
                    if (itemCount < value) { // 不满足
                        break;
                    }
                } else {
                    continue;
                }
                isAllFit = true;
            }
            if (isAllFit) {
                //抽中
                UserTurnItem newItem = new UserTurnItem();
                newItem.setIndex(-1);
                newItem.setExist(true);
                newItem.setAwardId(configAwardVo.getId());
                player.getMaster().getSaveList().add(CutSaveKey.USER_TURNTABLE);
                return newItem;
            }
        }
        return null;
    }

    //
    private int getRoundMax(PlayerInfoVo player) {
        Integer poolId = player.getTurnTable().getPoolId();
        ConfigWheelInfoVo wheelConfig = dataConfigService.getConfigWheelInfoConfig(poolId);
        if (ObjectUtil.isNull(wheelConfig)) {
            return 0;
        }
        return wheelConfig.getMax();
    }

    @Override
    public TurntableInfo packTurnTableData(PlayerInfoVo player) {
        UserTurnTableVo turnTable = player.getTurnTable();
        Set<Integer> awardList = turnTable.getAwardList();
        //获取转盘
        List<ConfigAwardVo> turnList = configActionUtil.getAwardPoolById(turnTable.getPoolId());
        if (ObjectUtil.isNull(turnList)) {
            return null;
        }
        List<ConfigAwardVo> backList = Lists.newArrayList();
        for (ConfigAwardVo configAwardVo : turnList) {
            // 是否已经转过
            boolean flag = awardList.contains(configAwardVo.getId());
            if (flag) {
                continue;
            }
            // 是否满足条件
            flag = this.conditionSuccess(player, configAwardVo);
            if (!flag) {
                continue;
            }
            //
            backList.add(configAwardVo);
        }
        TurntableInfo info = new TurntableInfo();
        info.setTurnId(turnTable.getPoolId());

        //
        List<TurnItemDto> turnItemList = Lists.newArrayList();
        List<UserTurnItem> turnData = turnTable.getTurnData();
        for (UserTurnItem turnDatum : turnData) {
            TurnItemDto n = new TurnItemDto();
            n.setExist(turnDatum.isExist());
            n.setAwardIndex(turnDatum.getIndex());
            n.setAwardId(turnDatum.getAwardId());
            turnItemList.add(n);
        }
        // TurnItemDto
        info.setTurnItemList(turnItemList);
        return info;
    }

    // 当前配置是否能满足条件
    private boolean conditionSuccess(PlayerInfoVo player, ConfigAwardVo configAwardVo) {
        // 检查奖励条件是否满足
        Integer[][] conditions = configAwardVo.getShowCondition();
        if (conditions == null || conditions.length == 0 || conditions[0] == null || conditions[0].length < 2) {
            return false;
        }
        Integer conditionType = conditions[0][0];
        Integer requiredValue = conditions[0][1];
        if (TurnDisplayRulesType.GOLD.getValue().equals(conditionType) || TurnDisplayRulesType.LOTTERY.getValue().equals(conditionType) || TurnDisplayRulesType.USER_POOL.getValue().equals(conditionType)) {
            //用户背包
            Integer currentValue = userBagService.getItemCount(player, conditionType);
            //道具低于
            if (ObjectUtil.isNotEmpty(currentValue) && currentValue <= requiredValue) {
                return true;
            }
        }
        if (TurnDisplayRulesType.SHARE.getValue().equals(conditionType)) {
            //用户分享次数
            Integer currentValue = player.getActivity().getShareCount();
            if (currentValue <= requiredValue) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void checkTurnRelease(PlayerInfoVo player, Integer roundId) {
        // 处于复活中则不改变转盘
        boolean isInRevive = userFlowService.isInRevive(player);
        if (isInRevive) {
            return;
        }
        UserTurnTableVo turnTable = player.getTurnTable();
        if (turnTable.getPoolId().equals(roundId)) {
            return;
        }
        //获取转盘
        List<ConfigAwardVo> turnList = configActionUtil.getAwardPoolById(roundId);
        if (ObjectUtil.isNull(turnList)) {
            return;
        }
        //
        turnTable.setPoolId(roundId);
        // 拉取10个
        int maxCount = this.getRoundMax(player);
        List<ConfigAwardVo> backList = Lists.newArrayList();
        for (ConfigAwardVo configAwardVo : turnList) {
            // 是否满足条件
            boolean flag = this.conditionSuccess(player, configAwardVo);
            if (!flag) {
                continue;
            }
            //
            backList.add(configAwardVo);
            if (backList.size() >= maxCount) {
                break;
            }
        }
        // 填充用户数据
        List<UserTurnItem> turnData = Lists.newArrayList();
        for (ConfigAwardVo configAwardVo : backList) {
            UserTurnItem item = new UserTurnItem();
            item.setExist(false);
            item.setAwardId(configAwardVo.getId());
            int index = turnData.size();
            item.setIndex(index);
            turnData.add(item);
        }
        // 打乱 turnData
        java.util.Collections.shuffle(turnData);
        //
        turnTable.setTurnData(turnData);
        turnTable.setAwardList(Sets.newHashSet());
        player.getMaster().getSaveList().add(CutSaveKey.USER_TURNTABLE);
    }

    @Override
    public void updatePlayerData(PlayerInfoVo player, UserTurnItem newItem, boolean setExist) {
        Integer awardId = newItem.getAwardId();
        UserTurnTableVo turnTable = player.getTurnTable();
        List<UserTurnItem> turnData = turnTable.getTurnData();
        if (ObjectUtil.isNotNull(awardId)) {
            turnTable.getAwardList().add(awardId);
            //
            if (setExist) {
                for (UserTurnItem turnDatum : turnData) {
                    if (turnDatum.getAwardId().equals(newItem.getAwardId())) {
                        turnDatum.setExist(true);
                        break;
                    }
                }
            }

            turnTable.getAwardList().add(awardId);
            player.getMaster().getSaveList().add(CutSaveKey.USER_TURNTABLE);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveToDb(PlayerInfoVo player, String key) {
        if (key.equals(CutSaveKey.USER_TURNTABLE)) {
            DBUserTurntable dbData = new DBUserTurntable();
            dbData.setUid(player.getBase().getUid());
            dbData.setActivityId(player.getActivity().getActivityId());
            dbData.setPoolId(player.getTurnTable().getPoolId());

            Set<Integer> awardList = player.getTurnTable().getAwardList();
            String awardListStr = JSON.toJSONString(awardList);
            dbData.setAwardList(awardListStr);

            List<UserTurnItem> idxList = player.getTurnTable().getTurnData();
            String idxListStr = JSON.toJSONString(idxList);
            dbData.setTurnData(idxListStr);

            userTurntableDBService.updateData(dbData);
        }
        return true;
    }

    @Override
    public boolean loadFromDb(PlayerInfoVo player, Integer uid) {
        DBUserTurntable dbData = userTurntableDBService.loadData(uid, player.getActivity().getActivityId());
        if (!ObjectUtil.isNull(dbData)) {
            UserTurnTableVo playerTurnTable = player.getTurnTable();
            playerTurnTable.setPoolId(dbData.getPoolId());
            String awardListStr = dbData.getAwardList();
            Set<Integer> obj = JSON.parseObject(awardListStr, Set.class);
            playerTurnTable.setAwardList(obj);
            String turnListStr = dbData.getTurnData();
            List<UserTurnItem> userTurnItems = JSON.parseArray(turnListStr, UserTurnItem.class);
            playerTurnTable.setTurnData(userTurnItems);
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(PlayerInfoVo player, Integer uid) {
        DBUserTurntable dbData = new DBUserTurntable();
        dbData.setUid(uid);
        dbData.setActivityId(player.getActivity().getActivityId());
        dbData.setPoolId(player.getTurnTable().getPoolId());

        Set<Integer> awardList = player.getTurnTable().getAwardList();
        String awardListStr = JSON.toJSONString(awardList);
        dbData.setAwardList(awardListStr);

        List<UserTurnItem> turnDataList = player.getTurnTable().getTurnData();
        String idxListStr = JSON.toJSONString(turnDataList);
        dbData.setTurnData(idxListStr);


        return userTurntableDBService.insertData(dbData);
    }
}
